#include "scene/previewscene.h"
#include "material/gameobjectmaterial.h"
#include "material/particlematerial.h"
#include <mdxl/mdxparticlemanager.h>

CPreviewScene::CPreviewScene() :
CScene(){
    m_rGameObjectMaterial = NEW CGameObjectMaterial();
    m_rGameObjectMaterial->Init();

    m_rGameObjectRenderElementManager = NEW CRenderElementManager();

    m_tFogColor.Set( 165.0f / 255.0f, 153.0f / 255.0f, 127.0f / 255.0f, 1.0f );
    m_fFogNear = 3000.0f, m_fFogFar = 10000.0f;

    m_tClearColor.Set( 0.0f, 0.0f, 0.0f, 0.5f );

    m_rParticleMaterial = NEW CParticleMaterial();
    m_rParticleMaterial->Init();


    m_rParticleManager = NEW CMDXParticleManager( 8192, 64 );

}
CPreviewScene::~CPreviewScene(){

}
bool32 CPreviewScene::Final(){
    m_rGameObjectRenderElementManager.Detach();
    m_rParticleManager.Detach();
    ClearAllChild();
    return True;
}
void CPreviewScene::Update( int32 nDelta, float fDelta ){
    CCamera*  _pCamera = m_rCamera.GetEntityData();
    _pCamera->UpdateRenderList();
    m_rGameObjectRenderElementManager->Update( _pCamera->m_tProjectionMatrix.m, _pCamera->m_tMatrixWorldInverse.m, _pCamera->m_tProjectionWorldInverse.m );
    CScene::Update( nDelta, fDelta );

    Quaternion _sFixCameraQuat = {-0.5f,-0.5f,-0.5f,0.5f};
    Quaternion _cameraQuat;
    math_quat_multiply( _cameraQuat, _pCamera->m_tQuaternion.m, _sFixCameraQuat );
   // math_quat_copy(_cameraQuat,m_rCamera->m_tQuaternion.m);

    m_rParticleManager->Update( &_pCamera->m_tPosition.X, &_pCamera->m_tView.X, _cameraQuat, nDelta, fDelta );

}
void CPreviewScene::Render( CTextureTarget* pTextureTarget, int32 nViewportWidth, int32 nViewportHeight ){
    Renderer_SetDepthTest( True );
    Renderer_SetDepthWrite( True );
    pTextureTarget->BeginRender( nViewportWidth, nViewportHeight );
    Renderer_SetClearColor( m_tClearColor.R, m_tClearColor.G, m_tClearColor.B, m_tClearColor.A );
    Renderer_Clear( True, True );
    
    CCamera* _pCamera = m_rCamera.GetEntityData();
    Matrix3 _vNormalM;
    Math_Matrix3_GetNormalMatrix( _pCamera->m_tMatrixWorldInverse.m, _vNormalM );

    m_rGameObjectMaterial->Begin();
    m_rGameObjectMaterial->SetProjectionMatrix( _pCamera->m_tProjectionMatrix.m );
    m_rGameObjectMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m );
    m_rGameObjectMaterial->SetNormalMatrix( _vNormalM );
    m_rGameObjectMaterial->SetFogInfo( m_tFogColor.GetPointer(), m_fFogNear, m_fFogFar );
    float _vLightDir1[3] = { 1.0f,1.0f,1.0f };
    m_rGameObjectMaterial->SetDirectionalLights_Direction( _vLightDir1 );
    float _vLightColor1[3] = { 2.0,2.0,2.0 };
    m_rGameObjectMaterial->SetDirectionalLights_Color(_vLightColor1);
    m_rGameObjectRenderElementManager->Render();
    m_rGameObjectMaterial->End();

    m_rParticleMaterial->Begin();
    m_rParticleMaterial->SetProjectionViewMatrix( _pCamera->m_tProjScreenMatrix.m );
    m_rParticleMaterial->SetViewMatrix( _pCamera->m_tMatrixWorldInverse.m );
    m_rParticleManager->Render( m_rParticleMaterial.GetEntityData() );
    m_rParticleMaterial->End();

    pTextureTarget->EndRender();
}
CSkyBox* CPreviewScene::GetSkyBox(){
    return NULL;
}
void CPreviewScene::AddChild( CGameObject* pGameObject ){
    CScene::AddChild( pGameObject );
    AddGameObjectRenderElement( pGameObject );
}
void CPreviewScene::RemoveChild( CGameObject* pGameObject ){
    RemoveGameObjectRenderElement( pGameObject );
    CScene::RemoveChild( pGameObject );
}

void CPreviewScene::AddGameObjectRenderElement( CGameObject* pGameObject ){
    CRenderElement* _vRenderElementHandle[2048];
    for( int32 i = 0, n = pGameObject->GetRenderElementHandles( _vRenderElementHandle, 2048 ); i < n; i++ ){
        CRenderElement* _pRenderElement = _vRenderElementHandle[i];
        _pRenderElement->m_pWorldM = pGameObject->m_vWorldM;
        _pRenderElement->m_pShadowMaterial = NULL;
        _pRenderElement->m_pMaterial = m_rGameObjectMaterial.GetEntityData();
        m_rGameObjectRenderElementManager->AddRenderElement( _pRenderElement );
    }
}
void CPreviewScene::RemoveGameObjectRenderElement( CGameObject* pGameObject ){
    if( pGameObject ){
        CRenderElement* _vRenderElementHandle[2048];
        for( int32 i = 0, n = pGameObject->GetRenderElementHandles( _vRenderElementHandle, 2048 ); i < n; i++ ){
            CRenderElement* _pRenderElement = _vRenderElementHandle[i];
            m_rGameObjectRenderElementManager->RemoveRenderElement( _pRenderElement );
        }
    }
}
